#include "Builder.h"



bool foundElem(vector < vector < string > > & vect, vector< string > & k){
	for (int i=0;i<vect.size();i++){
		if (vect[i]==k)
			return true;
	}
	return false;
};

void RemoveDuplicates(vector < vector<string> > & Vec ){
	sort(Vec.begin(),Vec.end());
	vector < vector<string> >  tempResult;
	for(int i=0;i<Vec.size();i++){
		vector<string> temp=Vec[i];
		tempResult.push_back(temp);
		while(i< Vec.size() && Vec[i]==temp)
			i++;
		if(i!=Vec.size()-1 && Vec[i]!= temp) 	i=i-1;	
		else if (i==Vec.size()-1 && Vec[i]!=temp) tempResult.push_back(Vec[i]);
	}
	Vec=tempResult;

	return;
};
void RemoveMapDuplicates(vector<vector< vector<string> > > & Vec ){
	sort(Vec.begin(),Vec.end());
	vector<vector < vector<string> > > tempResult;
	for(int i=0;i<Vec.size();i++){
		vector< vector< string> > temp=Vec[i];
		tempResult.push_back(temp);
		while(i< Vec.size() && Vec[i]==temp)
			i++;
		if(i< Vec.size() && Vec[i]!=temp) 	{ tempResult.push_back(Vec[i]);}

	}
	Vec=tempResult;
	return;
};
int IntTok(string  s){
	return atoi(( char *)s.c_str());
};
// cast a string to a double "2.2"---> 2.2
double RealTok(string  s){
	double result=atof(( char *)s.c_str());
	return result;
};
// cast a tuple "[a,b,c]" in string format to a vector of strings V[0]="a" V[1]="b"....
vector<string> TupleTok(string a){
	vector<string> temp;
	int i=0;
	while(a[i]!='[')
		i++;
	i++;
	string tp="";
	while(a[i]!=']'){
		if (a[i]!=' '){
			if (a[i]!=',')
				tp+=a[i];
			else{
				if(tp!=""){										
					temp.push_back(tp);
					tp="";
				}
			}
		}
		i++;
	}
	if (tp!="")
		temp.push_back(tp);
	return temp;
};
// cast a set "{[a,b],[d,e],[f,g]}" to a vector of vector of string
vector<vector<string> > SetTok(string  a){
	vector<vector<string> > temp;
	size_t pos=a.find("{");
	size_t poslast=a.find("}");
	if(poslast-pos==1){
	return temp;
	}
	string tempor=a.substr(pos);
	while(tempor[0]!='}'){
		pos=tempor.find("]");
		string tp=tempor.substr(0,pos+1);
		string tt=tempor.substr(pos+1,tempor.size());
		tempor=tt;
		temp.push_back(TupleTok(tp));
	}
	RemoveDuplicates(temp);
	return temp;
};
// cast a relation
vector<vector<string> > RelationTok(string  a){
	vector<vector<string> > temp;
	size_t pos=a.find("-");
	string tuple1=a.substr(0,pos);
	string tuple2=a.substr(pos,a.size());
	temp.push_back(TupleTok(tuple1));
	temp.push_back(TupleTok(tuple2));
	return temp;
};
// cast a Map
vector<vector<vector<string> > > MapTok(string  a){
	vector<vector<vector<string> > > temp;
	size_t pos=a.find("<");
	string tempor=a.substr(pos);
	while(tempor[0]!='>'){
		pos=tempor.find(")");
		string tp=tempor.substr(0,pos+1);
		string tt=tempor.substr(pos+1,tempor.size());
		tempor=tt;
		temp.push_back(RelationTok(tp));
	}
	RemoveMapDuplicates(temp);
	return temp;
};

Value * PianoAdd::Evaluate (Value *operand1, Value* operand2)const{
	if (operand1->getType()==FlagVal || operand2->getType()== FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()==RealVal || operand2->getType()==RealVal){
		double result=operand1->CastDouble()+operand2->CastDouble();
		Value * resultValue=new RealValue(result);
		return resultValue;
	}
	else {
		int result=operand1->getInt()+operand2->getInt();
		Value * resultValue=new IntValue(result);
		return resultValue;	
	}
};

Value * PianoSub::Evaluate (Value *operand1, Value* operand2)const{
	if (operand1->getType()==FlagVal || operand2->getType()== FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()==RealVal || operand2->getType()==RealVal){
		double result=operand1->CastDouble()-operand2->CastDouble();
		Value * resultValue=new RealValue(result);
		return resultValue;
	}
	else {
		int result=operand1->getInt()-operand2->getInt();
		Value * resultValue=new IntValue(result);
		return resultValue;	
	}	
};
	
Value * PianoMult::Evaluate (Value *operand1, Value* operand2)const{
	if ((operand1->CastDouble()==0 && operand1->getType()!=FlagVal)|| (operand2->CastDouble()==0 && operand2->getType()!=FlagVal)){
		Value * empty= new IntValue(0);
		return empty;
	}
	if (operand1->getType()==FlagVal || operand2->getType()== FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()!=RealVal || operand2->getType()!=RealVal){
		double result=operand1->CastDouble()*operand2->CastDouble();
		Value * resultValue=new RealValue(result);
		return resultValue;
	}
	else {
		int result=operand1->getInt()*operand2->getInt();
		Value * resultValue=new IntValue(result);
		return resultValue;
	}
};
	 
Value * PianoDiv:: Evaluate (Value *operand1, Value* operand2)const{
	if ((operand2->CastDouble()==0 && operand2->getType()!=FlagVal)){
		cout<<"Error: Divisor can't be zero"<<endl;
		exit(0);
	}
	if (operand1->getType()==FlagVal || operand2->getType()== FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()==RealVal || operand2->getType()==RealVal){
		double result=operand1->CastDouble()/operand2->CastDouble();
		Value * resultValue=new RealValue(result);
		return resultValue;
	}
	else {
		int result=operand1->getInt()/operand2->getInt();
		Value * resultValue=new IntValue(result);
		return resultValue;
	}		
};
Value* PianoIsLess::Evaluate (Value *operand1, Value* operand2)const{
	if (operand1->getType()==FlagVal || operand2->getType()== FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	double firstOperand=operand1->CastDouble();
	double secondOperand=operand2->CastDouble();
	if (firstOperand<secondOperand){
		Value * resultValue = new IntValue(1);
		return resultValue;
	}
	Value * resultValue=new IntValue(0);
	return resultValue;		
};
	
Value* PianoIsGreater::Evaluate (Value *operand1, Value* operand2)const{
	if (operand1->getType()==FlagVal || operand2->getType()== FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	double firstOperand=operand1->CastDouble();
	double secondOperand=operand2->CastDouble();
	if (firstOperand>secondOperand){
		Value * resultValue = new IntValue(1);
		return resultValue;
	}
	Value * resultValue=new IntValue(0);
	return resultValue;		
};

Value *  PianoIsEqual:: Evaluate (Value *operand1, Value* operand2)const{
	if (operand1->getType()==FlagVal || operand2->getType()== FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	double firstOperand=operand1->CastDouble();
	double secondOperand=operand2->CastDouble();
	if (firstOperand==secondOperand){
		Value * resultValue = new IntValue(1);
		return resultValue;
	}
	Value * resultValue=new IntValue(0);
	return resultValue;		
};
	
Value * PianoAnd::Evaluate (Value *operand1, Value* operand2)const{
	if ((operand1->getType()==IntVal && operand1->getInt()==0 )|| (operand2->getType()==IntVal && operand2->getInt()==0)){
		Value * empty= new IntValue(0);
		return empty;
		}
	if (operand1->getType()==FlagVal || operand2->getType()== FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
			
	if(operand1->getType()!=IntVal || operand2->getType()!=IntVal){
		cout<<"Error: Operands of the AND operator are only allowed to be Integer Numbers"<<endl;
		exit(0);	
	}
	int firstOperand=operand1->getInt();
	int secondOperand=operand2->getInt();
	if((firstOperand!=1 && firstOperand!=0) || (secondOperand!=1 && secondOperand!=0)){
		int result= firstOperand & secondOperand;
		Value * resultValue = new IntValue(result);
		return resultValue;
	}
	if (firstOperand==secondOperand){
		Value * resultValue = new IntValue(firstOperand);
		return resultValue;
	}
	Value * resultValue=new IntValue(0);
	return resultValue;		
};

Value * PianoOr::Evaluate (Value *operand1, Value* operand2)const{
	if ((operand1->getType()==IntVal && operand1->getInt()==0 )|| (operand2->getType()==IntVal && operand2->getInt()==0)){
		Value * empty= new IntValue(0);
		return empty;
	}
	if (operand1->getType()==FlagVal || operand2->getType()== FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()!=IntVal || operand2->getType()!=IntVal){
		cout<<"Error: Operands of the OR operator are only allowed to be Integer Numbers"<<endl;
		exit(0);	
	}
	int firstOperand=operand1->getInt();
	int secondOperand=operand2->getInt();
	if((firstOperand!=1 && firstOperand!=0) || (secondOperand!=1 && secondOperand!=0)){
		int result= firstOperand | secondOperand;
		Value * resultValue = new IntValue(result);
		return resultValue;
	}
	if (firstOperand==1 || secondOperand==1){
		Value * resultValue = new IntValue(1);
		return resultValue;
	}
	Value * resultValue=new IntValue(0);
	return resultValue;		
};

Value* PianoNot::Evaluate (Value *operand1)const{
	if (operand1->getType()==FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()!=IntVal){
		cout<<"Error: Operand of the NOT operator is only allowed to be Integer Numbers"<<endl;
		exit(0);	
	}
	int firstOperand=operand1->getInt();
	if(firstOperand!=0 && firstOperand!=1){
		int result= ~firstOperand;
		Value * resultValue = new IntValue(result);
		return resultValue;
	}
	if (firstOperand==0){
		Value * resultValue = new IntValue(1);
		return resultValue;
	}
	Value * resultValue=new IntValue(0);
	return resultValue;		
};
	
Value * PianoUnion::Evaluate (Value *operand1, Value* operand2)const{
	if (operand1->getType()==FlagVal || operand2->getType()== FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()!=SetVal || operand2->getType()!=SetVal){
		cout<<"Error: Operands of the UNION operator are only allowed to be Sets"<<endl;
		exit(0);	
	}
	vector<vector<string> > firstOperand=operand1->getSet();
	vector<vector<string> > secondOperand=operand2->getSet();
	vector<vector<string> > result=firstOperand;
	for (int i=0;i<secondOperand.size();i++){
		if(!foundElem(firstOperand,secondOperand[i]))
		result.push_back(secondOperand[i]);
	}
	Value * resultValue=new SetValue(result);
	return resultValue;
};
	
Value * PianoIntersection::Evaluate (Value *operand1, Value* operand2)const{
	if ((operand1->getType()==SetVal && operand1->CastDouble()==0) || (operand2->getType()==SetVal && operand2->CastDouble()==0)){
		Value * empty= new SetValue("{}");
		return empty;
	}
	if (operand1->getType()==FlagVal || operand2->getType()==FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()!=SetVal || operand2->getType()!=SetVal){
		cout<<"Error: Operands of the INTER operator are only allowed to be Sets"<<endl;
		exit(0);	
	}
	vector<vector<string> > firstOperand=operand1->getSet();
	vector<vector<string> > secondOperand=operand2->getSet();
	vector<vector<string> > result;
	for (int i=0;i<secondOperand.size();i++){
		if(foundElem(firstOperand,secondOperand[i]) )
			result.push_back(secondOperand[i]);
	}
	Value *resultValue=new SetValue(result);
	return resultValue;
};
Value * PianoCartesianPro::Evaluate (Value *operand1, Value* operand2)const{
	if (operand1->getType()==FlagVal || operand2->getType()==FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()!=SetVal || operand2->getType()!=SetVal){
		cout<<"Error: Operands of the CPRODUCT operator are only allowed to be Sets"<<endl;
		exit(0);	
	}
	vector<vector<string> > firstOperand=operand1->getSet();
	vector<vector<string> > secondOperand=operand2->getSet();
	vector<vector<string> > result;
	vector<string> temp;
	for (int i=0;i<firstOperand.size();i++){
		for(int j=0;j<secondOperand.size();j++){
			 temp=firstOperand[i];
			for (int k=0;k<secondOperand[j].size();k++)
				temp.push_back(secondOperand[j][k]);
				result.push_back(temp);
				temp.erase(temp.begin(),temp.end());
			}
		}
	Value * resultValue=new SetValue(result);
	return resultValue;
};
Value*  PianoScalarPro::Evaluate (Value *operand1, Value* operand2)const{
	if(operand2->getType()==FlagVal || operand1->getType()==FlagVal){
		Value* empty= new FlagValue(0);	
		return empty;	
	}
	if(operand1->getType()!=RealVal && operand1->getType()!=IntVal){
		cout<<"Error: First Operand of Operator SPRODUCT should be a number"<<endl;
		exit(0);		
	}
	if(operand2->getType()!=SetVal){
		cout<<"Error: Second Operand of Operator SPRODUCT should be a Set"<<endl;
		exit(0);		
	}
	vector<vector<string> > secondOperand= operand2->getSet();
	vector<vector<string> > returnResult;
	vector <string> tempVec;
	for(int i=0;i< secondOperand.size();i++){
		for(int j=0; j< secondOperand[i].size();j++){
			string s= secondOperand[i][j];
			bool RealIntTuple=true;
			int counter=0;
			int k=0;
			while(s[k]!='\0' && counter<=1 && RealIntTuple){	
				if(s[k]=='.')
					counter++;
				else if(s[k]>57 || s[k]<48)
					RealIntTuple=false;
				k++;
			}
			if(counter==2 || !RealIntTuple){
				cout<<"Error: Second Operand of Operator SPRODUCT should be a Set of number tuples"<<endl;
				exit(0);
			}
			else if (counter==0){
				int result= IntTok(s)*operand1->CastDouble();
				ostringstream tempresult;
				tempresult<<result;
				string temp=tempresult.str();
				tempVec.push_back(temp);
			}
			else {	
				double result= RealTok(s)*operand1->CastDouble();
				ostringstream tempresult;
				tempresult<<result;
				string temp=tempresult.str();
				tempVec.push_back(temp);
			}
		}
		returnResult.push_back(tempVec);
		tempVec.erase(tempVec.begin(),tempVec.end());
	
	}
		
	Value * Result= new SetValue(returnResult);
	return Result;
};

Value* PianoIsSub::Evaluate (Value *operand1, Value* operand2)const{
	if (operand1->getType()==SetVal && operand1->CastDouble()==0){
		Value * empty= new IntValue(1);
		return empty;
	}
	if (operand1->getType()==FlagVal || operand2->getType()==FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()!=SetVal || operand2->getType()!=SetVal){
		cout<<"Error: Operands of the ISSUB operator are only allowed to be Sets"<<endl;
		exit(0);	
	}
	vector<vector<string> > firstOperand=operand1->getSet();
	vector<vector<string> > secondOperand=operand2->getSet();
	if(firstOperand.size()>secondOperand.size()){
		Value *result = new IntValue(0);
		return result;
	}
	for (int i=0;i<firstOperand.size();i++){
		if(!foundElem(secondOperand,firstOperand[i])){
			Value *result = new IntValue(0);
			return result;
		}
	}
	Value * resultValue=new IntValue(1);
	return resultValue;
};
Value* PianoAssign::Evaluate (Value *operand1, Value* operand2)const{
	if (operand1->getType()==FlagVal || operand2->getType()==FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()==TupleVal && operand2->getType()==TupleVal){
		vector<string> firstoperand = operand1->getTuple();
		vector<string> secondoperand = operand2->getTuple();
		if(firstoperand==secondoperand){
			Value *result=new IntValue(1);
			return result;
		}
		Value *result=new IntValue(0);
		return result;
	}
	else if(operand1->getType()==SetVal && operand2->getType()==SetVal){
		vector<vector<string> > firstoperand = operand1->getSet();
		vector<vector<string> > secondoperand = operand2->getSet();
		if(firstoperand==secondoperand){
			Value *result=new IntValue(1);
			return result;
		}
		Value *result=new IntValue(0);
		return result;
	}
	else if(operand1->getType()==RelationVal && operand2->getType()==RelationVal){
		vector<vector<string> > firstoperand = operand1->getRelation();
		vector<vector<string> > secondoperand = operand2->getRelation();
		if(firstoperand==secondoperand){
			Value *result=new IntValue(1);
			return result;
		}
		Value *result=new IntValue(0);
		return result;
	}
	else if(operand1->getType()==MapVal && operand2->getType()==MapVal){
		vector<vector<vector<string> > > firstoperand = operand1->getMap();
		vector<vector<vector<string> > > secondoperand = operand2->getMap();
		if(firstoperand==secondoperand){
			Value *result=new IntValue(1);
			return result;
		}
		Value *result=new IntValue(0);
		return result;
	}
	else if((operand1->getType()==IntVal || operand1->getType()==RealVal) && (operand2->getType()==IntVal || operand2->getType()==RealVal) ){
		double first=operand1->CastDouble();
		double second=operand2->CastDouble();
		if (first==second){
			Value *result=new IntValue(1);
			return result;
		}
		Value *result=new IntValue(0);
		return result;
	}
	else{
		cout<<"Error: the type of the variable is inconsistent with that of its assigned value"<<endl;
		exit(0);
		}
};
Value* PianoSetIsEqual::Evaluate (Value * operand1, Value* operand2)const{
	if (operand1->getType()==FlagVal || operand2->getType()==FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if (operand1->getType()!=SetVal || operand2->getType()!=SetVal){
		cout<<"Error: Operands of the ISEQUAL operator should be Sets"<<endl;	
		exit(0);
	}
	vector<vector<string> > firstOperand=operand1->getSet();
	vector<vector<string> > secondOperand=operand2->getSet();
	if(firstOperand.size()!=secondOperand.size()){
		Value *result = new IntValue(0);
		return result;
	}
	for (int i=0;i<firstOperand.size();i++){
		if(firstOperand[i]!=secondOperand[i]){
			Value *result = new IntValue(0);
			return result;
		}
	}
	Value * resultValue=new IntValue(1);
	return resultValue;
};
Value* PianoComplement:: Evaluate(Value* operand1,Value* operand2)const{ 
	if (operand1->getType()==FlagVal || operand2->getType()==FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if (operand1->getType()!=SetVal || operand2->getType()!=SetVal){
		cout<<"Error: Operands of the COMP operator should be Sets"<<endl;	
		exit(0);
	}
	vector<vector<string> > firstOperand=operand1->getSet();
	vector<vector<string> > secondOperand=operand2->getSet();
	vector<vector<string> > result;
	bool IsSub= true;
	if(firstOperand.size()>secondOperand.size())
		IsSub=false;
	if(!IsSub){
		cout<<"Error: Size of the Universe should be greater than any of its subsets"<<endl;
		exit(0);
	}
	int i=0;
	while (i<firstOperand.size() && IsSub){
		if(!foundElem(secondOperand,firstOperand[i]))
			IsSub=false;
		i++;
	}
	if(!IsSub){
		cout<<"Error: Operand1 of the operator COMP should be a subset of Operand2"<<endl;
		exit(0);
	}
	i=0;
	while(i<secondOperand.size()){	
		if(!foundElem(firstOperand,secondOperand[i]))
			result.push_back(secondOperand[i]);
		i++;
	}
	Value* resultReturn=new SetValue(result);
	return resultReturn;
};
Value* PianoCardinality:: Evaluate(Value* operand1)const{
	if (operand1->getType()==FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()!=SetVal){
		cout<<"Error: Cardin Operator can only take an argument of type Set"<<endl;
		exit(0);
	}
	vector<vector<string> > Operand=operand1->getSet();
	int CardinOfSet=Operand.size();
	Value* empty= new IntValue(CardinOfSet);
	return empty;
};
Value* PianoComposition::Evaluate(Value* operand1 ,Value* operand2)const{ 
	if(operand1->getType()==FlagVal || operand2->getType()==FlagVal){
		Value* empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()!=MapVal || operand2->getType()!=MapVal){
		cout<<"Error: Both operands of the operator COMPO should be of type Map"<<endl;
		exit(0);
	}
	vector<vector<vector<string> > > firstOperand=operand1->getMap();
	vector<vector<vector<string> > > secondOperand=operand2->getMap();
	vector<vector<vector<string> > > result;
	vector<vector<string> > domainOfMap1;
        vector<vector<string> > codomainOfMap2; 
	for(int i=0;i< firstOperand.size(); i++)
		domainOfMap1.push_back(firstOperand[i][1]);
	for(int i=0;i< secondOperand.size();i++)
			codomainOfMap2.push_back(secondOperand[i][0]);
	for(int i=0; i< domainOfMap1.size();i++){
		bool match=false;
		for(int j=0; j< codomainOfMap2.size();j++){
			if(codomainOfMap2[j]==domainOfMap1[i]){
				vector<vector<string> > temp;
				temp.push_back(firstOperand[i][0]);
				temp.push_back(secondOperand[j][1]);
				result.push_back(temp);
				match=true;
			}
		}
		if(!match){
			cout<<"Error: Domain and Codomain of the Maps doesn't match"<<endl;
			exit(0);
		}
	}
		
	Value* returnResult = new MapValue (result); 
	return returnResult;
};
Value* PianoSubstitution::Evaluate(Value* operand1 ,Value* operand2)const{ 
	if(operand1->getType()==FlagVal || operand2->getType()==FlagVal){
		Value* empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()!=MapVal){
		cout<<"Error: First Operand of the operator SUBS should be of type Map"<<endl;
		exit(0);
	}
	if(operand2->getType()!=SetVal){
		cout<<"Error: Second Operand of the operator SUBS should be of type Set"<<endl;
		exit(0);
	}
	vector<vector<vector<string> > > firstOperand= operand1->getMap();
	vector<vector<string> > 	 secondOperand=operand2->getSet();
																	
	for(int i=0;i< firstOperand.size();i++){
		if(firstOperand[i][0].size()!=1 || firstOperand[i][1].size()!=1){
			cout<<"Error: Map of SUBS must be a map from a tuple of size one to another tuple of size one "<<endl;
			exit(0);			
		}

		for(int j=0;j<	secondOperand.size();j++){
			for(int k=0;k< secondOperand[j].size();k++){
				if(secondOperand[j][k]==firstOperand[i][0][0])
					secondOperand[j][k]=firstOperand[i][1][0];
			}
		}	
	}
			
	Value* result= new SetValue(secondOperand);
	return result;
};
Value* PianoProjection::Evaluate(Value* operand1 ,Value* operand2)const{ 
	if(operand1->getType()==FlagVal || operand2->getType()==FlagVal){
		Value* empty= new FlagValue(0);
		return empty;	
	}
	vector<vector<string> > result;
	if(operand1->getType()==SetVal && operand2->getType()==MapVal){
		vector<vector<string> > firstOperand=operand1->getSet();
		vector<vector<vector<string> > > secondOperand=operand2->getMap();
		for(int i=0;i< firstOperand.size();i++){
			for(int j=0;j< secondOperand.size();j++){
				if(firstOperand[i]==secondOperand[j][0]){
					result.push_back(secondOperand[j][1]);
				}
			}
		}
		Value* returnResult=new SetValue(result);
		return returnResult;	
	}
	else if(operand1->getType()==MapVal && operand2->getType()==SetVal){
		vector<vector<vector<string> > > firstOperand=operand1->getMap();
		vector<vector<string> > secondOperand=operand2->getSet();
		for(int i=0;i< secondOperand.size();i++){
			for(int j=0;j< firstOperand.size();j++){
				if(secondOperand[i]==firstOperand[j][0])
					result.push_back(secondOperand[i]);
			}
		}
		Value* returnResult=new SetValue(result);
		return returnResult;
		}
	else{
		cout<<"Error: Invalid type of operand of operator PROJ"<<endl;	
		exit(0);
	}	
};
Value* PianoExist::Evaluate(Value* operand1,Value* operand2)const{
	if (operand1->getType()==FlagVal || operand2->getType()==FlagVal){
		Value * empty= new FlagValue(0);
		return empty;
	}
	if(operand1->getType()!=TupleVal){
		cout<<"Error: First Operand of operator EXISTS should be a tuple"<<endl;
		exit(0);
	}
	if(operand2->getType()!=SetVal){
		cout<<"Error: Second Operand of operator EXISTS should be a Set"<<endl;
		exit(0);
	}
	vector<string> first=operand1->getTuple();
	vector<vector<string> > second= operand2->getSet();
	for (int i=0;i<second.size();i++){
		if(first==second[i]){
			Value *result=new IntValue(1);
			return result;
		}
	}
	Value* result= new IntValue(0);
	return result;
};
Value* PianoThereExists::Evaluate(Value* operand1,BaseNode* operand2) const{
	if((operand2->AdjNodes[1]->Val->getType())==FlagVal){
		Value* temp= new FlagValue(0);	
		return temp;			
	}
	if(!(operand2->AdjNodes[1]->Val->getType()==RealVal) && !(operand2->AdjNodes[1]->Val->getType()==IntVal)){
  	 	cout<<"Error: Condition of operator THEREEXISTS should be a number"<<endl;
  		exit(0);
	}
	vector<vector<string> > firstOperand=operand1->getSet();
	for(int i=0;i<firstOperand.size();i++){
		Value * tempTuple=new TupleValue(firstOperand[i]);
		Value* size=new RealValue(tempTuple->CastDouble());
		bool RealIntTuple=true;
		int counter=0;
		string s=firstOperand[i][0];
		int j=0;
		while(s[j]!='\0' && counter<=1 && RealIntTuple){	
			if(s[j]=='.')
				counter++;
			if(s[j]>57 && s[j]<48)
				RealIntTuple=false;
			j++;
		}
		if((size->getReal())!=1 || !RealIntTuple || counter==2){
			Value* temp= operand2->Evaluate(size,operand2->AdjNodes[1]->Val);
			if(temp->getInt()==1){
				Value* temp = new IntValue(1);
				return temp;
			}
		}
		else{
			if(counter==1){
				 Value* tempval=new RealValue(s);
				 Value* temp= operand2->Evaluate(tempval,operand2->AdjNodes[1]->Val);
				 if(temp->getInt()==1)
					return temp;
			}
			else {
				 Value* tempval=new IntValue(s);
				 Value* temp= operand2->Evaluate(tempval,operand2->AdjNodes[1]->Val);
		 		 if(temp->getInt()==1)
					return temp;
			}
		}
	
	}
	Value * temp =new IntValue(0);
	return temp;		
};

Value * PianoForEvery::Evaluate(Value* operand1,BaseNode * operand2)const{
	if((operand2->AdjNodes[1]->Val->getType())==FlagVal){
		Value* temp= new FlagValue(0);	
		return temp;			
	}
	if(!(operand2->AdjNodes[1]->Val->getType()==RealVal) && !(operand2->AdjNodes[1]->Val->getType()==IntVal))	{
  	 	cout<<"Error: Condition of operator FOREVERY should be a number"<<endl;
  		exit(0);
	}
	vector<vector<string> > firstOperand=operand1->getSet();
	for(int i=0;i<firstOperand.size();i++){	
		Value * tempTuple=new TupleValue(firstOperand[i]);
		Value* size=new RealValue(tempTuple->CastDouble());
		bool RealIntTuple=true;
		int counter=0;
		string s=firstOperand[i][0];
		int j=0;
		while(s[j]!='\0' && counter<=1 && RealIntTuple){	
			if(s[j]=='.')
				counter++;
			if(s[j]>57 && s[j]<48)
				RealIntTuple=false;
			j++;
		}
		if((size->getReal())!=1 || !RealIntTuple || counter==2){
			Value* temp= operand2->Evaluate(size,operand2->AdjNodes[1]->Val);
			if(temp->getInt()==0){
				Value* temp = new IntValue(0);
				return temp;
			}
		}
		else{
			if(counter==1){
				 Value* tempval=new RealValue(s);
				 Value* temp= operand2->Evaluate(tempval,operand2->AdjNodes[1]->Val);
				 if(temp->getInt()==0)
					return temp;
				}
				else {
				 Value* tempval=new IntValue(s);
				 Value* temp= operand2->Evaluate(tempval,operand2->AdjNodes[1]->Val);
		 		 if(temp->getInt()==0)
				return temp;
				}
			}	
		}
	Value * temp =new IntValue(1);
	return temp;			
};
/**     \brief    Function that removes spaces from a string to make Tokenization easier
*/	
string SpaceRemover(string a){
	string temp="";
	for (int i=0;i<a.size();i++)
		if(a[i]!=' ')
			temp+=a[i];
	return temp;
};

/**     \brief    Function that takes an input file of mathematical statements and maps each variable inside it to a value.
*/
map<string,string> ParseAssignmentFile(char * fileName){
	ifstream inf(fileName);
	string temp;
	getline(inf,temp);
	map<string,string> AssignedValue;
	while(!inf.eof() && temp!=""){
		size_t pos;
		pos=temp.find(":=");
		string half1=temp.substr(0,pos);
		string half2=temp.substr(pos+2,temp.size());
		half1=SpaceRemover(half1);
		half2=SpaceRemover(half2);
		AssignedValue[half1]=half2;
		getline(inf,temp);
	}
	return AssignedValue;
}
/**     \brief    Function that recursively returns the value of some BaseNode (class defined earlier) using breadth first traversal. Variable nodes that have not been defined yet are also assigned a Flag Value.
*/
Value * GetValue(BaseNode *a){
	if (a->AdjNodes.size()==0){
		return a->Val;
	}
	else if (a->name=="FOREVERY" || a->name=="THEREEXISTS")
		return a->Evaluate(GetValue(a->AdjNodes[0]),a->AdjNodes[1]);
	else if (a->AdjNodes.size()==1){
		return a->Evaluate(GetValue(a->AdjNodes[0]));
	}
	else if (a->AdjNodes.size()==2 || a->name=="SUBS"){
		return a->Evaluate(GetValue(a->AdjNodes[0]),GetValue(a->AdjNodes[1]));
	}
}
void CheckTree:: TreeConstructor(RealGraph G,string Check){
	AssignedValue=ParseAssignmentFile((char *)Check.c_str());
	Value * EmptyValue= new FlagValue(0);
	bool *Visited=new bool [G.Nodes.size()];
	for (int i=0;i<G.Nodes.size();i++)
		Visited[i]=false;
	for (int i=0;i<G.Nodes.size();i++){
		if (G.Nodes[i].data==":="){
			BaseNode * current = new PianoAssign(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="+"){
			BaseNode * current = new PianoAdd(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="-"){
			BaseNode * current = new PianoSub(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="*"){
			BaseNode * current = new PianoMult(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="/"){
			BaseNode * current = new PianoDiv(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data==">"){
			BaseNode * current = new PianoIsGreater(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="<"){
			BaseNode * current = new PianoIsLess(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="="){
			BaseNode * current = new PianoIsEqual(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="AND"){
			BaseNode * current = new PianoAnd(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="OR"){
			BaseNode * current = new PianoOr(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="NOT"){
			BaseNode * current = new PianoNot(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="INTER"){
			BaseNode * current = new PianoIntersection(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="UNION"){
			BaseNode * current = new PianoUnion(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="COMP"){
			BaseNode * current = new PianoComplement(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="COMPO"){
			BaseNode * current = new  PianoComposition(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="EXIST"){
			BaseNode * current = new PianoExist(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="CPRODUCT"){
			BaseNode * current = new PianoCartesianPro(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="SPRODUCT"){
			BaseNode * current = new PianoScalarPro(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);

		}
		else if (G.Nodes[i].data=="SUBS"){
			BaseNode * current = new PianoSubstitution(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);

		}
		else if (G.Nodes[i].data=="CARDIN"){
			BaseNode * current = new PianoCardinality(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="ISSUB"){					
			BaseNode * current = new PianoIsSub(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}	
		else if (G.Nodes[i].data=="ISEQUAL"){
			BaseNode * current = new PianoSetIsEqual(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="FOREVERY"){
			BaseNode * current = new PianoForEvery(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}
		else if (G.Nodes[i].data=="PROJ"){
			BaseNode* current = new PianoProjection(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type);
			newTree.addNode(current);
		}		
		else if (G.Nodes[i].type=="SET" || G.Nodes[i].type=="INT" || G.Nodes[i].type=="REAL" || G.Nodes[i].type=="TUPLE" || G.Nodes[i].type=="RELATION" || G.Nodes[i].type=="MAP" ){
			if(AssignedValue[G.Nodes[i].data]==""){
				BaseNode * current = new OperandNode(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type,EmptyValue);
				newTree.addNode(current);
			}
			else{
				Value* Content;
				if (G.Nodes[i].type=="SET")
					Content=new SetValue(AssignedValue[G.Nodes[i].data]);
				else if (G.Nodes[i].type=="INT")
					Content=new IntValue(AssignedValue[G.Nodes[i].data]);
				else if (G.Nodes[i].type=="REAL")
					Content=new RealValue(AssignedValue[G.Nodes[i].data]);
				else if (G.Nodes[i].type=="TUPLE")
					Content=new TupleValue(AssignedValue[G.Nodes[i].data]);
				else if (G.Nodes[i].type=="RELATION")
					Content=new RelationValue(AssignedValue[G.Nodes[i].data]);
				else
					Content=new MapValue(AssignedValue[G.Nodes[i].data]);
				BaseNode *current = new OperandNode(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type,Content);
				newTree.addNode(current);
			}
		}
		else{
			size_t pos;
			pos=G.Nodes[i].data.find("->");
			Value *Content;
			if (pos!=string::npos){
				Content=new RelationValue(G.Nodes[i].data);
			}
			else if(G.Nodes[i].data[0]=='['){
				Content=new TupleValue(G.Nodes[i].data);
			}
			else if (G.Nodes[i].data[0]=='{'){
				Content=new SetValue(G.Nodes[i].data);
			}
			else if (G.Nodes[i].data[0]=='<'){
				Content=new MapValue(G.Nodes[i].data);
			}
			else{	size_t pos1;
				pos1=G.Nodes[i].data.find(".");
				if (pos1!=string::npos){
				Content=new RealValue(G.Nodes[i].data);
				}
				else
				Content=new IntValue(G.Nodes[i].data);
			}
			BaseNode * current = new OperandNode(G.Nodes[i].data,G.Nodes[i].Fake,G.Nodes[i].type,Content);
			newTree.addNode(current);	
		}
	}
	for (int i=0;i<G.Edges.size();i++){
		if (G.Edges[i].weight!="definition"){
			AugEdge a(newTree.Nodes[newTree.FakeToIndex[G.Edges[i].Fakesource]],newTree.Nodes[newTree.FakeToIndex[G.Edges[i].FakeDest]],G.Edges[i].weight);
			newTree.addEdge(a);
			Visited[newTree.FakeToIndex[G.Edges[i].FakeDest]]=true;	
		}
		else{
			SpecialNodes.push_back(newTree.Nodes[newTree.FakeToIndex[G.Edges[i].Fakesource]]);
			RootsOfSpecialNodes.push_back(newTree.Nodes[newTree.FakeToIndex[G.Edges[i].FakeDest]]);
		}
	}
	for (int i=0;i<G.Nodes.size();i++)
		if (!Visited[i])
			PotentialRoots.push_back(newTree.Nodes[i]);
	for (int i=0;i<RootsOfSpecialNodes.size();i++){
		for (int j=0;j<RootsOfSpecialNodes.size();j++){
			if(SpecialNodes[j]->Val->getType()==FlagVal){
				Value *Check=GetValue(RootsOfSpecialNodes[j]->AdjNodes[1]);
				if (Check->getType()!=FlagVal){
					SpecialNodes[j]->SetBaseNodeVal(Check);
					for (int k=0;k<newTree.Nodes.size();k++){
						if(newTree.Nodes[k]->name==SpecialNodes[j]->name)
							newTree.Nodes[k]->SetBaseNodeVal(Check);
					}
				}
			}
		}
	}

	for (int i=0;i<SpecialNodes.size();i++){
		if(SpecialNodes[i]->Val->getType()==FlagVal){
			cout<<"Need More Information"<<endl;
			return;
		}
	}
	for (int i=0;i<PotentialRoots.size();i++){
		Value *Check = GetValue(PotentialRoots[i]);
		if (Check->getType()==FlagVal){
			cout<<"Need More Information"<<endl;
			return ;
		}
		else if(Check->getInt()!=1){
			cout<<"Not Satisfied"<<endl;
			return ;
		}
	}
	cout<<"Satisfied"<<endl;
	return;
	
}
	
